const express = require("express");
const logger = require("morgan");
const bodyParser = require("body-parser");
const cors = require("cors");
const requestIp = require('request-ip');
const searcher = require('node-ip2region').create();
const geoip = require('geoip-lite');
const sourcemap = require('./utils')
const {
  UserAction,
  ErrorLog,
  VisitLog,
  UserLog,
  HttpLog,
} = require("./models/index");

const app = express();

app.use(logger("dev"));
app.use(bodyParser.json());
app.use(bodyParser.text());

app.all("/*", cors());

app.use("/api/get/pvuv", async (req, res) => {
  const curDate = new Date()
  curDate.setHours(0, 0, 0, 0)
  const startTime = curDate.getTime();
  curDate.setHours(23, 59, 59, 999)
  const endTime = curDate.getTime()
  const items = await VisitLog.distinct('currentPage');

  const pv = items.length;
  const query = { createTime: {
          $gte: startTime,
          $lt: endTime
        }}
  const uv = await UserLog.find().count();
   const titems = await VisitLog.distinct('currentPage',query);

   const tpv = titems.length;
   const tuv = await UserLog.find(query).count();
  res.json({
    uv,
    pv,
    tuv,
    tpv
  });
});
app.use("/api/get/error500", async (req, res) => {
  
   res.json({
    code:500,
    data:'',
  });
});
app.use("/api/get/error0", async (req, res) => {
  
   res.json({
    code:0,
    data:'',
  });
});
app.use("/api/get/userAction", async (req, res) => {
  const page = req.query.page;
  const total = await UserAction.find().count();
  const data = await UserAction.find()
    .sort({ createTime: -1 })
    .limit(10)
    .skip(10 * (page - 1));
  res.json({
    total,
    pages: Math.ceil(total / 10),
    data,
  });
});
//用户轨迹
app.use("/api/get/userTrackList", async (req, res) => {
  const userId = req.query.userId;
  // const total = await ErrorLog.find().count();
  const page = 1; // 当前页码
    const pageSize = 40; // 每页数量
    const skip = (page - 1) * pageSize; // 跳过的文档数
    console.log(userId)
const pipeline = [
      // 步骤1：从第一个集合开始
      { $match: {userId} }, // 可以添加筛选条件
      { $project: { 
          data: '$$ROOT', 
          collectionName: { $literal: 'errorlog' },
          createTime: 1, // 确保所有集合都有相同的时间字段
          userId:1
        } 
      },
      
      // 步骤2：合并第二个集合
      { $unionWith: {
          coll: 'userlogs',
          pipeline: [
            { $match: { userId } },
            { $project: { 
                data: '$$ROOT', 
                collectionName: { $literal: 'userlogs' },
                createTime: 1 , // 确保所有集合都有相同的时间字段
          userId:1
              } 
            }
          ]
        }
      },
      
      // 步骤3：合并第三个集合
      { $unionWith: {
          coll: 'pvs',
          pipeline: [
            
              { $match: { userId } },
            { $project: { 
                data: '$$ROOT', 
                collectionName: { $literal: 'pvs' },
                createTime: 1 , // 确保所有集合都有相同的时间字段
          userId:1
              } 
            }
          ]
        }
      },
      
      // 步骤4：合并第四个集合
      { $unionWith: {
          coll: 'http',
          pipeline: [
            { $match: { userId } },
            { $project: { 
              
                data: '$$ROOT', 
                collectionName: { $literal: 'http' },
                createTime: 1 , // 确保所有集合都有相同的时间字段
          userId:1
              } 
            }
          ]
        }
      },
      
      // 步骤5：按时间排序
      { $sort: { createTime: -1 } }, // -1 表示降序（最新在前）
      { $facet: {
          paginatedResults: [
            { $skip: skip },
            { $limit: pageSize },
            { $project: { 
                _id: 0,
                collection: '$collectionName',
                data: 1,
                createTime: 1,
                userId:1,
              } 
            }
          ],
          totalCount: [
            { $count: 'count' }
          ]
        }
      },
      // 步骤6：分页
      { $skip: skip },
      { $limit: pageSize },
      
      // 步骤7：格式化结果（可选）
 
      { $project: {
          data: '$paginatedResults',
          total: { $arrayElemAt: ['$totalCount.count', 0] }
        }
      }
    ];
    
  const result = await ErrorLog.aggregate(pipeline);
if(result && result.length){
  const list = result[0];
  const {data,total} = list
res.json({
    total,
    // pages: Math.ceil(total / 10),
    data,
  });
}else{
  res.json({
    total:0,
    // pages: Math.ceil(total / 10),
    data:[],
  });
}

});
app.use("/api/get/errorLog", async (req, res) => {
  const page = req.query.page;
  const total = await ErrorLog.find().count();
  const data = await ErrorLog.find()
    .sort({ createTime: -1 })
    .limit(10)
    .skip(10 * (page - 1));
  res.json({
    total,
    pages: Math.ceil(total / 10),
    data,
  });
});

app.use("/api/get/visitLog", async (req, res) => {
  const page = req.query.page;
  const total = await VisitLog.find().count();
  const data = await VisitLog.find()
    .sort({ createTime: -1 })
    .limit(10)
    .skip(10 * (page - 1));
  res.json({
    total,
    pages: Math.ceil(total / 10),
    data,
  });
});
app.use("/api/get/httpLog", async (req, res) => {
  const page = req.query.page;
  const total = await HttpLog.find().count();
  const data = await HttpLog.find()
    .sort({ createTime: -1 })
    .limit(10)
    .skip(10 * (page - 1));
  res.json({
    total,
    pages: Math.ceil(total / 10),
    data,
  });
});
app.use("/report/actions", (req, res) => {
  const logs = typeof req.body === "object" ? req.body : JSON.parse(req.body);
  const origin = req.headers.origin //请求来源地址
  console.log(logs);
  logs?.forEach(async (item) => {
    const log = JSON.parse(item);
    const { appId, userId, type, data, currentTime, currentPage, ua } = log;
    if (appId !== "授权id")
      switch (type) {
        case "action":
          const userAction = new UserAction({
            appId,
            userId,
            actionType: data.actionType,
            data: JSON.stringify(data.data),
            createTime: currentTime,
            currentPage,
            ua,
          });
          await userAction.save();
          break;
        case "error":
          const errorLog = new ErrorLog({
            appId,
            userId,
            errorType: data.errorType,
            errMsg: JSON.stringify(data.message),
            error: data.error,
            col: data.col,
            row: data.row,
            createTime: currentTime,
            currentPage,
            ua,
          });
          await errorLog.save();
          break;
        case "visit":
          const visitLog = new VisitLog({
            appId,
            userId,
            stayTime: data.stayTime,
            createTime: currentTime,
            currentPage: data.page,
            ua,
          });
          if (!data.page) {
            return;
          }
          await visitLog.save();
          break;
        case "http":
          const httpLog = new HttpLog({
            appId,
            userId,
            url: data.url,
            status: data.status,
            duration: data.duration,
            response: JSON.stringify(data.error),
            request: JSON.stringify(data.request),
            createTime: currentTime,
            currentPage,
            ua,
          });
          await httpLog.save();
          break;
        case "user":
          const target = await UserLog.find({ userId, appId });
          const ip = requestIp.getClientIp(req);
          const result = searcher.btreeSearchSync('124.118.224.22');
           console.log(result);
          if (target?.length === 0) {
            const userLog = new UserLog({
              appId,
              userId,
              ip,
              geo:result.region,
              createTime:new Date().getTime(),
              ua,
            });
            await userLog.save();
          }
          break;
        default:
          break;
      }
  });

  res.send("发送成功");
});

app.use(function (req, res, next) {
  const err = new Error("Not Found");
  err.status = 404;
  next(err);
});

app.use(function (err, req, res, next) {
  res.locals.message = err;
  res.locals.error = req.app.get("env") === "development" ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.json({
    code: "error",
    info: err,
  });
});

const port = process.env.PORT || 3009;
app.listen(port, () => {
  console.log(`server is running on port ${port}`);
});
sourcemap.init()



require("./db");
